/*
 * TODO: this is not done
 *
  lcd-i2c.c - I2C LCD display control
  Part of Grbl32

  Copyright (c) 2018-2019 Thomas Truong

  Grbl is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Grbl is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <string.h>
#include "lcd-i2c.h"
#include "stm32utilities.h"


#if ( defined(STM32F13) || defined(STM32F46) )	//-- only available on F13 and F46

#define LCD_ADDR (0x27 << 1)
#define PIN_RS    (1 << 0)
#define PIN_EN    (1 << 2)
#define BACKLIGHT (1 << 3)
#define LCD_DELAY_MS 5

I2C_HandleTypeDef *pHI2C = NULL;



//-------------------------------------------------------------------------------
void I2C_Scan()
{
  char info[] = "Scanning I2C bus...\r\n";
  uart_sendstr(info);

  HAL_StatusTypeDef res;
  for (uint16_t i = 0; i < 128; i++)
    {
    res = HAL_I2C_IsDeviceReady(pHI2C, i << 1, 1, 10);
    if (res == HAL_OK)
      {
      char msg[64];
      sprintf(msg, "0x%02X", i);
      uart_sendstr(msg);
      }
    else
      {
      uart_sendstr(".");
      }
    }

  uart_sendstr("\r\n");
}
//-------------------------------------------------------------------------------
HAL_StatusTypeDef LCD_SendInternal(uint8_t lcd_addr, uint8_t data, uint8_t flags)
{
  HAL_StatusTypeDef res;
  for (;;)
    {
    res = HAL_I2C_IsDeviceReady(pHI2C, lcd_addr, 1, HAL_MAX_DELAY);
    if (res == HAL_OK)
      break;
    }

  uint8_t up = data & 0xF0;
  uint8_t lo = (data << 4) & 0xF0;

  uint8_t data_arr[4];
  data_arr[0] = up | flags | BACKLIGHT | PIN_EN;
  data_arr[1] = up | flags | BACKLIGHT;
  data_arr[2] = lo | flags | BACKLIGHT | PIN_EN;
  data_arr[3] = lo | flags | BACKLIGHT;

  res = HAL_I2C_Master_Transmit(pHI2C, lcd_addr, data_arr, sizeof(data_arr), HAL_MAX_DELAY);
  HAL_Delay(LCD_DELAY_MS);
  return res;
}
//-------------------------------------------------------------------------------
void LCD_SendCommand(uint8_t lcd_addr, uint8_t cmd)
{
  LCD_SendInternal(lcd_addr, cmd, 0);
}
//-------------------------------------------------------------------------------
void LCD_SendData(uint8_t lcd_addr, uint8_t data)
{
  LCD_SendInternal(lcd_addr, data, PIN_RS);
}
//-------------------------------------------------------------------------------
void LCD_Init(I2C_HandleTypeDef *HI2C, uint8_t lcd_addr)
{
	pHI2C = HI2C;

  // 4-bit mode, 2 lines, 5x7 format
  LCD_SendCommand(lcd_addr, 0b00110000);
  // display & cursor home (keep this!)
  LCD_SendCommand(lcd_addr, 0b00000010);
  // display on, right shift, underline off, blink off
  LCD_SendCommand(lcd_addr, 0b00001100);
  // clear display (optional here)
  LCD_SendCommand(lcd_addr, 0b00000001);
}
//-------------------------------------------------------------------------------
void LCD_SendString(uint8_t lcd_addr, char *str)
{
  while (*str)
    {
    LCD_SendData(lcd_addr, (uint8_t) (*str));
    str++;
    }
}
//-------------------------------------------------------------------------------

#endif //( defined(STM32F13) || defined(STM32F46) )
